package com.hq.ims.data.config.mybatis;

import com.baomidou.mybatisplus.core.conditions.AbstractWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.TableInfo;
import com.baomidou.mybatisplus.core.metadata.TableInfoHelper;
import com.baomidou.mybatisplus.core.toolkit.Constants;
import com.baomidou.mybatisplus.core.toolkit.LambdaUtils;
import com.baomidou.mybatisplus.core.toolkit.support.ColumnCache;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.hq.authority.utils.AppUtils;
import com.hq.mybatis.utils.sql.ExecutorPluginUtils;
import com.hq.web.inf.user.ITokenUserInfo;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.SqlCommandType;
import org.apache.ibatis.plugin.Intercepts;
import org.apache.ibatis.plugin.Invocation;
import org.apache.ibatis.plugin.Signature;
import org.springframework.stereotype.Component;

import java.util.Map;

/**
 * JBP
 *
 * @email 526666031@qq.com
 */
@Component
@Intercepts({
        @Signature(type = Executor.class, method = "update", args = {MappedStatement.class, Object.class}),
})
public class UpdateIntercepts extends MybatisPlusInterceptor {

    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        Object[] args = invocation.getArgs();
        String processSql = ExecutorPluginUtils.getSqlByInvocation(invocation);
        MappedStatement ms = (MappedStatement) args[0];
        if (SqlCommandType.UPDATE != ms.getSqlCommandType()) {
            return invocation.proceed();
        }
        Object param = args[1];
        if (param instanceof Map) {
            Map map = (Map) param;
            //updateById(et), update(et, wrapper);
            Object et = map.getOrDefault(Constants.ENTITY, null);
            if (et != null) {
                return super.intercept(invocation);
            } else {
                AbstractWrapper<?, ?, ?> aw = (AbstractWrapper<?, ?, ?>) map.getOrDefault(Constants.WRAPPER, null);
                if (aw != null) {
                    if (aw instanceof LambdaUpdateWrapper) {
                        LambdaUpdateWrapper lm = (LambdaUpdateWrapper) aw;
                        Class<?> entityClass = ((MappedStatement) invocation.getArgs()[0]).getParameterMap().getType();
                        Map<String, ColumnCache> columnMap = LambdaUtils.getColumnMap(entityClass);
                        TableInfo info = TableInfoHelper.getTableInfo(entityClass);
                        boolean updateDateTimeIsExists = columnMap.containsKey("UPDATEDATETIME");
                        boolean updateUserNameIsExists = columnMap.containsKey("UPDATEUSERNAME");
                        boolean updateUserIdIsExists = columnMap.containsKey("UPDATEUSERID");

                        if (updateDateTimeIsExists) {
                            lm.setSql("update_date_time = now()");
                        }
                        ITokenUserInfo currentUser = AppUtils.getCurrentUserNoException();
                        if (currentUser == null) {
                            return invocation.proceed();
                        }
                        if (updateUserNameIsExists) {
                            lm.setSql(String.format("update_user_name = '%s'", currentUser.getRealName()));
                        }
                        if (updateUserIdIsExists) {
                            lm.setSql(String.format("update_user_id = '%s'", currentUser.getId()));
                        }
                    }
                }
                return invocation.proceed();
            }
        }
        return invocation.proceed();
    }
}
